RubyとJRubyとでパフォーマンスを比較してみた
はじめに
以前Ruby(CRuby)で作成したアプリで、大量データ(数千万件オーバー)のCSVを読み込み、文字列変換をして別ファイルに出力するという処理を実装しました。同じような処理をRubyの別処理系で行った場合、どのようになるのかが気になったので、ちょっと実験してみました。
今回使う処理系や実行マシンについて
タイトルにもあるように、通常のRuby(CRuby)とJRubyとで比較しました。Rubyの他の処理系としてはRubiniusなどもありますが、それはまた別の機会にしたいと思います。
Ruby、JRubyのバージョンについて
今回使用したRuby、JRubyのバージョンは以下の通りです。
- Ruby - 2.1.0
- JRuby - 1.7.9
実行マシンについて
実行マシンについては以下の通りです。なおVirtualBox上のUbuntuで実行しています。
- CPU - Core i7 2.80GHz
- Momory - 8G
- OS - Ubuntu 14.04 LTS
実行ソースと結果
実行ソース
実行したソースは以下の通りです。
benchmark.rb
INPUT_FILE_PATH = './input.csv' OUTPUT_FILE_PATH = 'output.csv'
class DataDate def initialize(data_date) date_ary = data_date.split(' ') @date = date_ary[0] @time = date_ary[1] end
def out_datetime ymd = @date.split('/') hm = @time.split(':') t = Time.new(ymd[0].to_i, ymd[1].to_i, ymd[2].to_i, hm[0].to_i, hm[1].to_i) t = t + (9 * 60 * 60) t.strftime('%Y-%m-%d %p %I:%M') end end
def write_line(out, input) data = input.chomp.split(',') line = Array.new line << data[9].gsub('{#}', 'jjjj') line << data[8] line << data[7] line << data[6] line << data[5] line << data[4] line << data[3] line << data[2] line << data[1] line << DataDate.new(data[0]).out_datetime out.puts(line.join(',')) end start_time = Time.now open(OUTPUT_FILE_PATH, 'w'){|out| open(INPUT_FILE_PATH) {|input| input.each{|line| write_line(out, line) } } } end_time = Time.now puts 'processing time = ' + (end_time - start_time).to_s [/ruby]
動きとしては
- 100万件、10カラムのCSV(input.csv)を一行ずつ読み込む
- 全カラムの左右並び順を入れ替える
- 特定の文字列({#})を置き換える
- 日付のフォーマットを変換する
- これらの結果を別ファイル(output.csv)に出力する
といったことを行っております。
また読み込んだCSVファイル(input.csv)は以下のような書式となっております。
input.csv
2014/1/1 10:00,bbbbb,ccccc,ddddd,eeeee,fffff,ggggg,hhhhh,iiiii,j{#} 2014/1/2 10:00,bbbbb,ccccc,ddddd,eeeee,fffff,ggggg,hhhhh,iiiii,j{#} 2014/1/3 10:00,bbbbb,ccccc,ddddd,eeeee,fffff,ggggg,hhhhh,iiiii,j{#} 2014/1/4 10:00,bbbbb,ccccc,ddddd,eeeee,fffff,ggggg,hhhhh,iiiii,j{#} 2014/1/5 10:00,bbbbb,ccccc,ddddd,eeeee,fffff,ggggg,hhhhh,iiiii,j{#} (以下略、100万件まで)
実行結果
上記のRubyスクリプトを、Ruby(CRuby)とJRubyとで5回ずつ実行してみました。但し、JRubyの実行時には最適化されるようオプションを設定しています。以下に、実行時のコマンドと5回の実行時間を載せておきます。
Ruby
ruby benchmark.rb
実行回数 | 時間(秒) |
---|---|
1回目 | 41.188 |
2回目 | 40.368 |
3回目 | 38.445 |
4回目 | 38.257 |
5回目 | 37.563 |
JRuby
jruby --server -v --fast benchmark.rb
実行回数 | 時間(秒) |
---|---|
1回目 | 29.338 |
2回目 | 28.285 |
3回目 | 27.143 |
4回目 | 29.536 |
5回目 | 30.598 |
平均すると
- Ruby - 39.164秒
- JRuby - 28.98秒
とJRubyのほうが早かったです。
まとめ
上記のような結果となりましたが、あくまで今回試したサンプルソースでの結果であるため、あらゆる場合でJRubyが早いとは限らないでしょう。またJRubyの実行時には最適化されるようオプションを設定したこともあり、これらを設定しない場合はJRubyのほうが遅かったことも合わせて書いておきます。